
#include "server.h"
#include "connection.h"
#include "define.h"
#include <cstring>
#include <functional>
#include <memory>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>


Server::Server(Loop * loop)
{
    m_loop = loop;
}

Server::~Server()
{
    m_channel->DelEvent();
}

bool Server::InitServerConfig(ServerConfig server_config)
{
    m_server_config = server_config;
    return true;
}

bool Server::ListenServer(int port)
{
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0)
    {
        return false;
    }
    struct sockaddr_in sai{};
    sai.sin_family = AF_INET;
    sai.sin_port   = htons(port);
    sai.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(fd, (struct sockaddr*)&sai, sizeof(sai)) != 0)
    {
        return false;
    }
    listen(fd, 10024);
    std::shared_ptr<TcpSocket> socket = std::make_shared<TcpSocket>(fd);
    if (m_server_config.m_black_status)
    {
        socket->NonBlack();
    }
    m_channel = std::make_shared<Channel>(m_loop, socket);
    m_channel->ReadFuncCallback(std::bind(&Server::ReadAble, this, std::placeholders::_1, std::placeholders::_2));
    m_channel->AddEvent(EmIoIn | EmIoOneShot);
    m_socket = socket;
    return true;
}

void Server::OnConnectionCallback(OnConnection && func)
{
    m_onconn = func;
}

void Server::OnDisConnectionCallback(DisConnection && func)
{
    m_disconn = func;
}

void Server::OnMessageCallback(OnMessage && func)
{
    m_onmessage = func;
}

void Server::ReadAble(std::shared_ptr<Channel> channel, std::shared_ptr<TcpSocket> socket)
{
    int result = accept(m_socket->GetSocket(), nullptr, nullptr);
    if (result <= 0)
    {
    
    }
    else
    {
        TRACE("new socket number : {}", result);
        std::shared_ptr<TcpSocket> new_socket = std::make_shared<TcpSocket>(result); 
        if (m_server_config.m_black_status)
        {
            new_socket->NonBlack();
        }
        std::shared_ptr<Connection> connection = std::make_shared<Connection>(m_loop, this, new_socket);
        m_connect_map[connection->Index()] = connection;
        if (m_onconn)
        {
            m_onconn(connection);
        }
    }
    m_channel->ModEvent(EmIoIn | EmIoOneShot);
}


void Server::MessageFromConn(std::shared_ptr<Connection> conn, std::shared_ptr<SocketBuffer> buffer)
{
    if (m_onmessage)
    {
        m_onmessage(conn, buffer);
    }
}

void Server::DisConnFromConn(std::shared_ptr<Connection> conn)
{
    if (m_disconn)
    {
        m_disconn(conn);
    }
    m_connect_map.erase(conn->Index());
}
